home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / linux / src / atalnx_3.lzh / atari-linux-0.01pl3 / tools / atari / bootstra.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-16  |  13.9 KB  |  567 lines

  1. /*
  2. ** boot_atari.c -- This program loads the Atari Linux kernel and launches it.
  3. **
  4. ** Copyright 1994 by Björn Brauel and Roman Hodek
  5. **
  6. **
  7. ** This file is subject to the terms and conditions of the GNU General Public
  8. ** License.  See the file README.legal in the main directory of this archive
  9. ** for more details.
  10. **
  11. */
  12.  
  13. #include <osbind.h>
  14. #include <stddef.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include <file.h>
  20. #include <types.h>
  21. #include <unistd.h>
  22.  
  23. #define m68k
  24. #define PORTAR
  25.  
  26. /* #define    DEBUG    */
  27.  
  28.  
  29. /* Atari bootstrap include file */
  30. #include "bootstra.h"
  31.  
  32. /* required Atari linux include files */
  33. # include "a.out.h"
  34.  
  35. #include "bootinfo.h"
  36.  
  37. /* temporary stack size */
  38. #define TEMP_STACKSIZE    1024
  39.  
  40. #define    FAST_RAM_START    0x1000000
  41.  
  42. long *fastram_top = (long *)0x5a4,
  43.      *fastram_valid = (long *)0x5a8;
  44.  
  45. /* The following variables are global, because they have to be accessed
  46.  * after the stack has been changed.
  47.  */
  48.  
  49. struct bootinfo bi;
  50.  
  51. long  KSTART_MEM;
  52. long  KMEM_SIZE;     
  53. long  kbi_offset;
  54.  
  55. char  *memptr;
  56. struct exec kexec;
  57. long   rd_size;
  58.  
  59. void   *copy_addr;
  60. long   copy_len;
  61.  
  62.  
  63.  
  64. static void get_default_args( int *argc, char ***argv );
  65. static void waitkey( void );
  66.  
  67.  
  68. void usage(void)
  69. {
  70.     fprintf (stderr, "Usage:\n"
  71.          "\tbootstrap [-d] [-k kernel_executable] [-r ramdisk_file]"
  72.          " [option...]\n");
  73.     waitkey();
  74.     exit (EXIT_FAILURE);
  75. }
  76.  
  77. int main(int argc, char *argv[])
  78. {
  79.     long i,memreq;
  80.     int kfd,rfd;
  81.     int debugflag=0;
  82.     long offs;
  83.     char *kernel_name = "vmlinux";
  84.     char *ramdisk_name = NULL;
  85.     void *stack;
  86.     long savessp;
  87.  
  88.     rfd=-1;
  89.     /* print the greet message */
  90.     puts(" Atari Linux Bootstrap version 0.6");
  91.     puts("Copyright 1994 by Björn Brauel, Roman Hodek\n");
  92.  
  93.     if (argc == 1)
  94.         get_default_args( &argc, &argv );
  95.  
  96.     /* ++roman: get kernel and ramdisk name from the command line */
  97.     while( argc > 1 && argv[1][0] == '-' ) {
  98.         switch( argv[1][1] ) {
  99.             case 'k':
  100.                 if (argv[1][2]) {
  101.                     kernel_name = argv[1]+2;
  102.                     --argc; ++argv;
  103.                 }
  104.                 else if (argc > 2 && argv[2][0]) {
  105.                     kernel_name = argv[2];
  106.                     argc -= 2; argv += 2;
  107.                 }
  108.                 else
  109.                     usage();
  110.                 break;
  111.             case 'r':
  112.                 if (argv[1][2]) {
  113.                     ramdisk_name = argv[1]+2;
  114.                     --argc; ++argv;
  115.                 }
  116.                 else if (argc > 2 && argv[2][0]) {
  117.                     ramdisk_name = argv[2];
  118.                     argc -= 2; argv += 2;
  119.                 }
  120.                 else
  121.                     usage();
  122.                 break;
  123.             case 'd':
  124.                 debugflag = 1;
  125.                 --argc; ++argv;
  126.                 break;
  127.             case '?':
  128.             default:
  129.                 usage();
  130.         }
  131.     }
  132.     --argc; ++argv;
  133.  
  134.     /* machine is Atari */
  135.     bi.machtype = MACH_ATARI;
  136.     KSTART_MEM = 0x000000L;                              
  137.     KMEM_SIZE = 0x400000L;
  138.  
  139.     bi.cputype = CPU_68030;
  140.     bi.cputype |= FPU_68881;
  141.     bi.num_memory = 1;
  142.     bi.memory[0].addr=KSTART_MEM;
  143.     bi.memory[0].size=KMEM_SIZE;
  144.  
  145.     /* Test for TT Ram: I rely on undocumented system variables here,
  146.      * hope the compatibility gods won't damn me forever...
  147.      */
  148.     savessp = Super( 0L );
  149.     if (*fastram_valid == 0x1357bd13 && *fastram_top != 0) {
  150.         bi.memory[bi.num_memory].addr = FAST_RAM_START;
  151.         bi.memory[bi.num_memory].size = *fastram_top - FAST_RAM_START /* - PAGE_SIZE */;
  152.         bi.num_memory++;
  153.     }
  154.     Super( savessp );
  155.  
  156.     /* Copy remaining arguments into the boot info */
  157.     i = 0;
  158.     bi.command_line[0] = 0;
  159.     while (argc--) {
  160.         if ((i+strlen(*argv)+1) < CL_SIZE) {
  161.             i += strlen(*argv) + 1;
  162.             if (bi.command_line[0])
  163.                 strcat (bi.command_line, " ");
  164.             strcat (bi.command_line, *argv++);
  165.         }
  166.     }
  167.  
  168.     printf( "Command line is \"%s\"\n", bi.command_line );
  169.  
  170.     /* tell us where the kernel will go */
  171.     printf("\nThe kernel will be located at %08lx\n", KSTART_MEM);
  172.  
  173.     /* open kernel executable and read exec header */
  174.     if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
  175.         fprintf (stderr, "Unable to open kernel file %s\n", kernel_name);
  176.         waitkey();
  177.         exit (EXIT_FAILURE);
  178.     }
  179.  
  180.     if (read (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
  181.         fprintf (stderr, "Unable to read exec header from %s\n",
  182.              kernel_name);
  183.         waitkey();
  184.         exit (EXIT_FAILURE);
  185.     }
  186.  
  187.     if (ramdisk_name) {
  188.         if ((rfd = open (ramdisk_name, O_RDONLY)) == -1) {
  189.             fprintf (stderr, "Unable to open ramdisk file %s\n",
  190.                  ramdisk_name);
  191.             waitkey();
  192.             exit (EXIT_FAILURE);
  193.         }
  194.         /* record ramdisk size */
  195.         bi.ramdisk_size = (lseek (rfd, 0, SEEK_END)) >> 10;
  196.     } else
  197.         bi.ramdisk_size = 0;
  198.  
  199.     /* Ramdisk goes at the end of the last memory block */
  200.     rd_size = bi.ramdisk_size << 10;
  201.     bi.ramdisk_addr = bi.memory[bi.num_memory-1].addr +
  202.                       bi.memory[bi.num_memory-1].size - rd_size ;
  203.  
  204.     printf( "ramdisk size = %lx\n", (long)rd_size );
  205.     printf( "ramdisk addr = %lx\n", (long)bi.ramdisk_addr );
  206.  
  207.     /* find offset to boot_info structure */
  208.     offs = get_nlist (kernel_name, "_boot_info");
  209.     if (offs==0) {
  210.         perror ("get_nlist");
  211.         waitkey();
  212.         exit (EXIT_FAILURE);
  213.     } else {
  214.         kbi_offset = offs - kexec.a_entry;
  215.     }
  216.  
  217.     memreq = kexec.a_text + kexec.a_data + rd_size;
  218.     memptr = (char *)Malloc (memreq);
  219.     if (!memptr) {
  220.         fprintf (stderr, "Unable to allocate memory\n");
  221.         waitkey();
  222.         exit (EXIT_FAILURE);
  223.     }
  224.     printf( "Temporary load area is 0x%lx...0x%lx\n", (long)memptr, (long)(memptr+memreq-1) );
  225.  
  226.     {    long    load_st = (long)memptr,
  227.                 load_end = (long)memptr + memreq,
  228.                 dest_st = KSTART_MEM ,
  229.                 dest_end = KSTART_MEM + kexec.a_text + kexec.a_data +
  230.                                         kexec.a_bss + 8;
  231.     
  232.         if ((load_end >= dest_st && load_end < dest_end) ||
  233.             (dest_end >= load_st && dest_end < load_end)) {
  234.             fprintf( stderr, "\nOVERLAPPING OF LOAD AND BOOT AREA!!!\n\n" );
  235.             waitkey();
  236.             exit( -1 );
  237.         }
  238.         if (bi.ramdisk_addr < load_end) {
  239.             fprintf( stderr, "\nOVERLAPPING OF RAMDISK AND LOAD AREA!!!\n\n" );
  240.             waitkey();
  241.             exit( -1 );
  242.         }
  243.     }
  244.     
  245.     if (lseek (kfd, N_TXTOFF(kexec), SEEK_SET) == -1) {
  246.         fprintf (stderr, "Failed to seek to text\n");
  247.         Mfree ((void *)memptr);
  248.         waitkey();
  249.         exit (EXIT_FAILURE);
  250.     }
  251.     if (read (kfd, memptr + rd_size, kexec.a_text) != kexec.a_text) {
  252.         fprintf (stderr, "Failed to read text\n");
  253.         Mfree ((void *)memptr);
  254.         waitkey();
  255.         exit (EXIT_FAILURE);
  256.     }
  257.     if (lseek (kfd, N_DATOFF(kexec), SEEK_SET) == -1) {
  258.         fprintf (stderr, "Failed to seek to data\n");
  259.         Mfree ((void *)memptr);
  260.         waitkey();
  261.         exit (EXIT_FAILURE);
  262.     }
  263.     if (read (kfd, memptr + kexec.a_text + rd_size, kexec.a_data) != kexec.a_data) {
  264.         fprintf (stderr, "Failed to read data\n");
  265.         Mfree ((void *)memptr);
  266.         waitkey();
  267.         exit (EXIT_FAILURE);
  268.     }
  269.     close (kfd);
  270.  
  271.     if (rfd != -1) {
  272.         if (lseek (rfd, 0, SEEK_SET) == -1) {
  273.             fprintf (stderr, "Failed to seek to beginning of ramdisk file\n");
  274.             Mfree ((void *)memptr);
  275.             waitkey();
  276.             exit (EXIT_FAILURE);
  277.         }
  278.         if (read (rfd, memptr, rd_size) != rd_size) {
  279.             fprintf (stderr, "Failed to read ramdisk file\n");
  280.             Mfree ((void *)memptr);
  281.             waitkey();
  282.             exit (EXIT_FAILURE);
  283.         }
  284.         close (rfd);
  285.     }
  286.  
  287.     /* allocate temporary stack */
  288.     stack = (void *)Malloc((long)TEMP_STACKSIZE);
  289.     if (!stack) {
  290.         fprintf (stderr, "Unable to allocate memory for stack\n");
  291.         Mfree ((void *)memptr);
  292.         waitkey();
  293.         exit (EXIT_FAILURE);
  294.     }
  295.     printf( "Temporary stack is 0x%lx..0x%lx\n", (long)stack, (long)(stack + TEMP_STACKSIZE-1) );
  296.  
  297.     /* Allocate memory for copy routine. This must lie within the 
  298.      * destination address ranges (kernel mem and ramdisk mem).
  299.      */
  300.     copy_len = copy_kernel_end - copy_kernel;
  301.     do {
  302.         if (!(copy_addr = (void *)Malloc( copy_len ))) {
  303.             fprintf( stderr, "Unable to allocate memory for copy routine.\n" );
  304.             waitkey();
  305.             exit (EXIT_FAILURE);
  306.         }
  307.     } while( (long)copy_addr < KSTART_MEM+kexec.a_text+kexec.a_data+kexec.a_bss+8 ||
  308.              (long)copy_addr + copy_len > bi.ramdisk_addr );
  309.     
  310.     printf( "Copy routine will be located at %08lx.\n", (unsigned long)copy_addr );
  311.     memcpy( copy_addr, copy_kernel, copy_len );
  312.  
  313.     if (debugflag) {
  314.         if (bi.ramdisk_size)
  315.             printf ("RAM disk at %#lx, size is %ldK\n",    bi.ramdisk_addr,
  316.                     bi.ramdisk_size);
  317.  
  318.         printf ("\nKernel text at %#lx, code size %ld\n",
  319.             KSTART_MEM + N_TXTADDR(kexec), (long)kexec.a_text);
  320.         printf ("Kernel data at %#lx, data size %ld\n",
  321.             KSTART_MEM + N_DATADDR(kexec), (long)kexec.a_data );
  322.         printf ("Kernel bss  at %#lx, bss  size %ld\n",
  323.             KSTART_MEM + N_BSSADDR(kexec), (long)kexec.a_bss );
  324.  
  325.         printf ("\nKernel boot_info is at offset %#lx, physical %#lx, virtual %#lx\n",
  326.             kbi_offset, KSTART_MEM + kbi_offset,    kbi_offset + kexec.a_entry );
  327.  
  328.         printf ("\nKernel entry is %#lx\n", (unsigned long)kexec.a_entry );
  329.  
  330.         printf ("ramdisk dest top is %#lx\n", KSTART_MEM);
  331.         printf ("ramdisk lower limit is %#lx\n",
  332.             (unsigned long)(memptr));
  333.         printf ("ramdisk src top is %#lx\n",
  334.             (unsigned long)(memptr + rd_size));
  335.  
  336.         printf( "Load area is 0x%lx .. 0x%lx\n", (long)(KSTART_MEM - rd_size),
  337.                 (long)(KSTART_MEM + kexec.a_text + kexec.a_data + kexec.a_bss) );
  338.  
  339.         printf( "\nFound %d memory blocks:\n", bi.num_memory );
  340.         for( i = 0; i < bi.num_memory; ++i )
  341.             printf( "  0x%08lx .. 0x%08lx (0x%lx bytes)\n", 
  342.                     bi.memory[i].addr,
  343.                     bi.memory[i].addr + bi.memory[i].size - 1,
  344.                     bi.memory[i].size );
  345.  
  346.         printf ("\nType a key to continue the Linux boot...");
  347.         fflush (stdout);
  348.         getchar();
  349.     }
  350.  
  351.     /* copy boot info into the kernel */
  352.     memcpy( memptr + rd_size + kbi_offset, &bi, sizeof(bi) );
  353.  
  354.     /* wait for things to settle down */
  355.     sleep(2);
  356.  
  357.     /* Go into supervisor state and change stack*/
  358.     Super(0L);
  359.     change_stack(stack + TEMP_STACKSIZE - sizeof(long)); 
  360.     /* turn off caches */
  361.     cache_off(); 
  362.  
  363.     /* turn off any mmu translation */
  364.     disable_mmu ();  
  365.  
  366.     /* Turn off Interrupts */
  367.     raise_int();  
  368.  
  369.     __asm__ __volatile__ (
  370.         "movel    %0,a6\n\t"
  371.         "movel    %1,a5\n\t"
  372.         "movel    %2,a4\n\t"
  373.         "movel    %3,d7\n\t"
  374.         "movel    %4,d6\n\t"
  375.         "movel    %5,d5\n\t"
  376.         "movel    %6,a0\n\t"
  377.         "jmp    a0@"
  378.         : /* no outputs */
  379.         : "g" (memptr), "g" (KSTART_MEM+8), "g" (bi.ramdisk_addr),
  380.           "g" (kexec.a_text+kexec.a_data), "g" (kexec.a_bss),
  381.           "g" (rd_size), "g" (copy_addr)
  382.     );
  383.  
  384. #if 0
  385.     {
  386.         /*
  387.          * there may be problems here if the compiler optimizer
  388.          * doesn't put these variables in registers, and the
  389.          * stack space was allocated at the beginning of the function
  390.          * and we've changed the stack.
  391.          */
  392.         unsigned char *csrc, *cdest, *climit;
  393.         unsigned long *src, *dest, *limit;
  394.  
  395.         /*
  396.          * copy the kernel text and data to their final resting place.
  397.          * The text is padded out (in the a.out file) to a multiple of
  398.          * the page size.
  399.          */
  400.        
  401.         src = (unsigned long *)(memptr + rd_size);
  402.         dest = (unsigned long*)(KSTART_MEM + 8L);  /* first 8 bytes are ROM!! */
  403.         limit = (unsigned long *)(memptr + rd_size + kexec.a_text +
  404.                                   kexec.a_data + 8L);
  405.         while (src < limit)
  406.             *dest++ = *src++;
  407.  
  408.         /* clear kernel bss */
  409.         dest = (unsigned long *)(KSTART_MEM + kexec.a_text + kexec.a_data + 8L);
  410.         limit = dest + kexec.a_bss / sizeof(unsigned long);
  411.         while (dest < limit)
  412.             *dest++ = 0;
  413.  
  414.         /* copy the boot_info struct to the correct location */
  415.         cdest = (unsigned char *)KSTART_MEM + 8L + kbi_offset;
  416.         climit = cdest + sizeof (bi);
  417.         csrc = (unsigned char *)&bi;
  418.         while (cdest < climit)
  419.             *cdest++ = *csrc++;
  420.  
  421.         /* copy the ramdisk at end of mem */
  422.         dest = (unsigned long *)((u_long)bi.ramdisk_addr+(u_long)rd_size);
  423.         limit = (unsigned long *)((u_long)memptr);
  424.         src = (unsigned long *)((u_long)memptr + (u_long)rd_size);
  425.         while (src > limit)
  426.             *--dest = *--src; 
  427.  
  428.     }
  429.     
  430.     /* jump to start of kernel */
  431.     jump_to (KSTART_MEM + 8L); 
  432. #endif
  433.  
  434.     /* NOTREACHED */
  435.     return(0);
  436.  
  437. }
  438.  
  439.  
  440.  
  441. #define    MAXARGS        30
  442.  
  443. static void get_default_args( int *argc, char ***argv )
  444.  
  445. {    FILE        *f;
  446.     static char    *nargv[MAXARGS];
  447.     char        arg[256], *p;
  448.     int            c, quote, state;
  449.  
  450.     if (!(f = fopen( "bootargs", "r" )))
  451.         return;
  452.     
  453.     *argc = 0;
  454.     *argv = nargv;
  455.     nargv[(*argc)++] = "bootstra.ttp";
  456.  
  457.     quote = state = 0;
  458.     while( (c = fgetc(f)) != EOF ) {        
  459.  
  460.         if (state == 0) {
  461.             /* outside args, skip whitespace */
  462.             if (!isspace(c)) {
  463.                 state = 1;
  464.                 p = arg;
  465.             }
  466.         }
  467.         
  468.         if (state == 1) {
  469.             /* inside an arg: copy it into 'arg', obeying quoting */
  470.             if (!quote && (c == '\'' || c == '"'))
  471.                 quote = c;
  472.             else if (quote && c == quote)
  473.                 quote = 0;
  474.             else if (!quote && isspace(c)) {
  475.                 /* end of this arg */
  476.                 *p = 0;
  477.                 nargv[(*argc)++] = strdup(arg);
  478.                 state = 0;
  479.             }
  480.             else
  481.                 *p++ = c;
  482.         }
  483.     }
  484.     if (state == 1) {
  485.         /* last arg finished by EOF! */
  486.         *p = 0;
  487.         nargv[(*argc)++] = strdup(arg);
  488.     }
  489.     fclose( f );
  490.     
  491.     nargv[*argc] = 0;
  492. }    
  493.  
  494. long get_nlist(const char *fname, const char *symname)
  495. {
  496.     int fd = open (fname, O_RDONLY);
  497.     struct exec ex;
  498.     struct nlist *nl, *syms;
  499.     char *strs;
  500.     long back;
  501.     size_t filesize;
  502.     long strsize, numsyms;
  503.  
  504.     if (fd == -1)
  505.     return 0;
  506.  
  507.     read (fd, &ex, sizeof(ex));
  508.     if (!ex.a_syms) {
  509.     close (fd);
  510.     return 0;
  511.     }
  512.  
  513. #ifdef DEBUG
  514.     printf ("%ld bytes of symbol data\n", ex.a_syms);
  515. #endif
  516.  
  517.     syms = (struct nlist *)malloc (ex.a_syms);
  518.     if (!syms) {
  519.     close (fd);
  520.     return 0;
  521.     }
  522.     filesize=lseek (fd, N_SYMOFF(ex), SEEK_SET);
  523.     read (fd, syms, ex.a_syms);
  524.     numsyms = ex.a_syms / sizeof (struct nlist);
  525.     filesize = lseek (fd, 0L, SEEK_END);
  526.     strsize = filesize - N_STROFF(ex);
  527.     strs = (char *)malloc (strsize);
  528.     if (!strs) {
  529.     free (syms);
  530.     close (fd);
  531.     return 0;
  532.     }
  533.     lseek (fd, N_STROFF(ex), SEEK_SET);
  534.     read (fd, strs, strsize);
  535.     back=0;
  536.  
  537.  
  538.     for (nl = syms; nl < syms + numsyms; nl++) {
  539. #ifdef DEBUG
  540.     printf ("checking symbol number %d, name %s\n",
  541.         nl - syms, strs + nl->n_un.n_strx);
  542. #endif
  543.     if (strcmp (symname, strs + nl->n_un.n_strx) == 0
  544.         && nl->n_type == N_BSS | N_EXT) {
  545.         back = nl->n_value;
  546.         break;
  547.     }
  548.     }
  549.     free (strs);
  550.     free (syms);
  551.     close (fd);
  552.     return back;
  553. }
  554.  
  555.  
  556. static void waitkey( void )
  557.  
  558. {
  559.     fprintf( stderr, "\nPress any key.\n" );
  560.     while( !Bconstat(2) )
  561.         ;
  562.     (void)Bconin(2);
  563. }
  564.  
  565.  
  566.  
  567.